﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using Raven.Client;
using Raven.Client.Linq;

namespace Didaku.Data.Raven
{
    /// <summary>基于RavenDB的NoSql存储的单库的持久化虚实现
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="D"></typeparam>
    public abstract class RavenDbStore<T, D> : IRavenDbStore<T, D>
    {
        protected readonly DbMarket _DbMarket;

        public IDocumentSession Session { get { return _DbMarket.GetDocumentSession(); } }

        public virtual IRavenQueryable<T> Query
        {
            get { return _DbMarket.GetDocumentSession().Query<T>(); }
        }

        protected RavenDbStore(DbMarket dbMarket)
        {
            _DbMarket = dbMarket;
        }

        #region Implementation of IDbStore<T>

        /// <summary>按RavenDb的规则，真实Id前要加相应的前缀。这里用实体类来表达。
        /// </summary>
        /// <returns></returns>
        protected virtual string GetIdPrefix()
        {
            var prefix = GetType().Name.ToLower();
            return prefix.Replace("DbStore".ToLower(), "");
        }

        /// <summary>增加指定的实体记录
        /// </summary>
        public virtual int Add(params T[] entity)
        {
            try
            {
                var session = _DbMarket.GetDocumentSession();
                foreach (T ent in entity)
                {
                    session.Store(ent, string.Format("{0}s/{1}", GetIdPrefix(), GetEntityId(ent)));
                }
                session.SaveChanges();
                return entity.Length;
            }
            catch (Exception e)
            {
                return -1;
            }
        }

        /// <summary>移除指定的实体记录
        /// </summary>
        public virtual int Remove(params T[] entity)
        {
            try
            {
                var session = _DbMarket.GetDocumentSession();
                foreach (T ent in entity)
                    session.Delete(ent);
                session.SaveChanges();
                return entity.Length;
            }
            catch (Exception e)
            {
                return -1;
            }
        }

        /// <summary>删除指定ID的记录
        /// </summary>
        /// <param name="entityId"></param>
        /// <returns></returns>
        public virtual int Remove(params D[] entityId)
        {
            try
            {
                var session = _DbMarket.GetDocumentSession();
                foreach (D ent in entityId)
                {
                    var subEnt = session.Load<T>(ent.ToString());
                    session.Delete(subEnt);
                }
                session.SaveChanges();
                return entityId.Length;
            }
            catch (Exception e)
            {
                return -1;
            }
        }

        /// <summary>更新指定的实体记录
        /// </summary>
        public virtual int Update(params T[] entity)
        {
            try
            {
                var session = _DbMarket.GetDocumentSession();
                foreach (T ent in entity)
                {
                    session.Store(ent, string.Format("{0}s/{1}", GetType().Name.ToLower(), GetEntityId(ent)));
                }
                session.SaveChanges();
                return entity.Length;
            }
            catch (Exception e)
            {
                return -1;
            }
        }

        /// <summary>查找指定的实体记录
        /// </summary>
        public virtual T[] Find(params D[] entityId)
        {
            return _DbMarket.GetDocumentSession().Load<T>(entityId.Cast<string>());
        }

        /// <summary>获取一个实体的Id
        /// </summary>
        protected abstract string GetEntityId(T entity);

        #endregion
    }
}